package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.article.mapper.ApArticleConfigMapper;
import com.heima.article.mapper.ApArticleContentMapper;
import com.heima.article.mapper.ApArticleMapper;
import com.heima.article.mapper.AuthorMapper;
import com.heima.article.service.ApArticleService;
import com.heima.article.service.GeneratePageService;
import com.heima.common.constants.article.ArticleConstants;
import com.heima.common.constants.wemedia.WemediaConstants;
import com.heima.common.exception.CustException;
import com.heima.feign.AdminFeign;
import com.heima.feign.WemediaFeignClient;
import com.heima.model.admin.pojos.AdChannel;
import com.heima.model.article.dto.ArticleHomeDTO;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.article.pojos.ApArticleConfig;
import com.heima.model.article.pojos.ApArticleContent;
import com.heima.model.article.pojos.ApAuthor;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmNews;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class ApArticleServiceImpl extends ServiceImpl<ApArticleMapper, ApArticle>
    implements ApArticleService {

  @Autowired WemediaFeignClient wemediaFeignClient;
  @Autowired AdminFeign adminFeign;

  @Value("${file.minio.readPath}")
  String realPath;

  @Value("${file.oss.web-site}")
  private String webSite;

  @Autowired ApArticleConfigMapper apArticleConfigMapper;
  @Autowired ApArticleContentMapper apArticleContentMapper;
  @Autowired ApArticleMapper apArticleMapper;
  @Autowired GeneratePageService generatePageService;
  @Autowired RedisTemplate redisTemplate;

  @Transactional
  @Override
  public void publishArticle(Integer newsId) {
    // 1.查询并检验自媒体文章
    WmNews wmNews = getWmNesw(newsId);

    // 2.封装article
    ApArticle article = getApArticle(wmNews);

    // 3.保存或者修改article
    saveOrUpdateArticle(article);

    // 4.保存文章和config和content的关联关系
    saveContentAndConfig(wmNews, article);
    // TODO:页面的静态化
    generatePageService.generateArticlePage(wmNews.getContent(), article);
    // 更新wmmNews的状态
    updateWmNews(newsId, wmNews, article);
    // 7.TODO 通知索引库添加文章索引
  }

  /**
   * 加载文章列表
   *
   * @param type 0为加载更多 1为加载最新
   * @param dto
   * @return
   */
  @Override
  public ResponseResult load(Short type, ArticleHomeDTO dto) {
    // 给各个参数设置默认值
    Date maxBehotTime = dto.getMaxBehotTime();
    Date minBehotTime = dto.getMinBehotTime();
    Integer size = dto.getSize();
    String tag = dto.getTag();
    if (maxBehotTime == null) {
      dto.setMaxBehotTime(new Date());
    }
    if (minBehotTime == null) {
      dto.setMinBehotTime(new Date());
    }
    if (size == null) {
      dto.setSize(10);
    }
    if (tag == null) {
      dto.setTag("_all_");
    }
    List<ApArticle> apArticles = apArticleMapper.loadArticleList(dto, type);
    for (ApArticle apArticle : apArticles) {

      apArticle.setStaticUrl(realPath + apArticle.getStaticUrl());
    }
    return ResponseResult.okResult(apArticles);
  }
  /**
   * 根据参数加载文章列表
   *
   * @param loadtype 0为加载更多 1为加载最新
   * @param dto
   * @param firstPage 是否为首页 true 首页
   * @return
   */
  @Override
  public ResponseResult load2(Short loadtype, ArticleHomeDTO dto, boolean firstPage) {
    if (firstPage) {
      String articleListJson =
          (String)
              redisTemplate
                  .opsForValue()
                  .get(ArticleConstants.HOT_ARTICLE_FIRST_PAGE + dto.getTag());
      if (StringUtils.isNotBlank(articleListJson)) {
        List<ApArticle> apArticles = JSON.parseArray(articleListJson, ApArticle.class);
        for (ApArticle apArticle : apArticles) {
          //
          apArticle.setStaticUrl(webSite + apArticle.getStaticUrl());
        }
        ResponseResult result = ResponseResult.okResult(apArticles);
        result.setHost(webSite);
        return result;
      }
    }

    return load(loadtype,dto);
  }

  private void updateWmNews(Integer newsId, WmNews wmNews, ApArticle article) {
    wmNews.setStatus(WmNews.Status.PUBLISHED.getCode());
    wmNews.setArticleId(article.getId());
    ResponseResult result = wemediaFeignClient.updateWmNews(wmNews);
    if (result == null) {
      CustException.cust(AppHttpCodeEnum.SERVER_ERROR, "远程调用WmNews服务失败");
    }
  }

  /**
   * 保存config和content
   *
   * @param wmNews
   * @param article
   */
  private void saveContentAndConfig(WmNews wmNews, ApArticle article) {
    // 保存到config表中

    ApArticleConfig apArticleConfig = new ApArticleConfig();

    apArticleConfig.setArticleId(article.getId());
    apArticleConfig.setIsComment(true); // 是否可评论
    apArticleConfig.setIsForward(true); // 是否可转发
    apArticleConfig.setIsDown(false); // 是否下架
    apArticleConfig.setIsDelete(false); // 是否已经删除
    apArticleConfigMapper.insert(apArticleConfig);
    // 保存到content表中
    ApArticleContent apArticleContent = new ApArticleContent();

    apArticleContent.setArticleId(article.getId());
    apArticleContent.setContent(wmNews.getContent());
    apArticleContentMapper.insert(apArticleContent);
  }

  private void saveOrUpdateArticle(ApArticle apArticle) {

    if (apArticle.getId() == null) {
      // 无关联  新增 article
      // 保存文章
      apArticle.setCollection(0); // 收藏数
      apArticle.setLikes(0); // 点赞数
      apArticle.setComment(0); // 评论数
      apArticle.setViews(0); // 阅读数
      save(apArticle);
    } else {
      // 如果存在修改文章，删除之前的关联关系

      ApArticle article = getById(apArticle.getId());
      if (apArticle == null) {
        CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "查询的文章不存在");
      }
      // 修改文章
      updateById(apArticle);
      // 删除关联关系
      apArticleConfigMapper.delete(
          Wrappers.<ApArticleConfig>lambdaQuery()
              .eq(ApArticleConfig::getArticleId, apArticle.getId()));
      apArticleContentMapper.delete(
          Wrappers.<ApArticleContent>lambdaQuery()
              .eq(ApArticleContent::getArticleId, apArticle.getId()));
    }
  }

  /**
   * 封装article
   *
   * @param wmNews`
   * @return
   */
  @Autowired AuthorMapper authorMapper;

  private ApArticle getApArticle(WmNews wmNews) {

    ApArticle apArticle = new ApArticle();
    // 将wmNews的属性拷贝到article
    BeanUtils.copyProperties(wmNews, apArticle);
    apArticle.setLayout(wmNews.getType()); // 文章的布局
    apArticle.setId(wmNews.getArticleId());
    apArticle.setFlag((byte) 0);

    // 频道的信息
    ResponseResult<AdChannel> one = adminFeign.findOne(wmNews.getChannelId());
    AdChannel adChannel = one.getData();
    if (adChannel == null) {
      log.info("远程调用admin获取频道失败");
      CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, "远程调用失败");
    }
    apArticle.setChannelId(adChannel.getId());
    apArticle.setChannelName(adChannel.getName());

    // 获取作者的信息
    LambdaQueryWrapper<ApAuthor> wrapper = Wrappers.lambdaQuery();
    wrapper.eq(ApAuthor::getWmUserId, wmNews.getUserId());
    ApAuthor apAuthor = authorMapper.selectOne(wrapper);

    if (apAuthor == null) {
      CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "没有查询到对于的作者");
    }
    apArticle.setAuthorId(Long.valueOf(apAuthor.getId()));
    apArticle.setAuthorName(apAuthor.getName());
    return apArticle;
  }

  /**
   * 查询自媒体文章，并检验参数
   *
   * @param newsId
   * @return
   */
  private WmNews getWmNesw(Integer newsId) {
    if (newsId == null) {
      CustException.cust(AppHttpCodeEnum.DATA_NOT_EXIST, "id不存在");
    }
    // 进行远程调用，获取文章
    ResponseResult<WmNews> wmNewsById = wemediaFeignClient.findWmNewsById(newsId);
    WmNews wmNews = wmNewsById.getData();
    if (wmNews == null) {
      CustException.cust(AppHttpCodeEnum.REMOTE_SERVER_ERROR, "wemediaFeignClient远程调用失败");
    }
    // 获取文章的状态
    Short status = wmNews.getStatus();
    if (!WemediaConstants.WM_NEWS_AUTH_PASS.equals(status)
        && !WemediaConstants.WM_NEWS_AUTHED_STATUS.equals(status)) {
      log.error("文章发布失败 文章状态不为 4 或 8， 不予发布 , 文章id : {}", newsId);
      CustException.cust(AppHttpCodeEnum.SIGN_INVALID, "文章状态异常");
    }
    return wmNews;
  }
}
